package com.chengqs.tomdog.utils;

import java.util.Arrays;
import java.util.EnumSet;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import jakarta.servlet.DispatcherType;
import jakarta.servlet.Filter;
import jakarta.servlet.Servlet;
import jakarta.servlet.annotation.WebFilter;
import jakarta.servlet.annotation.WebInitParam;
import jakarta.servlet.annotation.WebServlet;

public class AnnoUtils {
    /**
     * 获取Servlet名称
     * @param clazz Servlet字节码文件
     * @return Servlet名称
     */
    public static String getServletName(Class<? extends Servlet> clazz) {
        // 获取@WebServlet注解
        WebServlet w = clazz.getAnnotation(WebServlet.class);
        if (w != null && !w.name().isEmpty()) {
            // 如果@WebServlet注解不为空并且name属性不为空，则返回注解的name属性
            return w.name();
        }
        return defaultNameByClass(clazz);
    }

    /**
     * 获取Filter名称
     * @param clazz Filter字节码文件
     * @return Filter名称
     */
    public static String getFilterName(Class<? extends Filter> clazz) {
        // 获取@WebFilter注解
        WebFilter w = clazz.getAnnotation(WebFilter.class);
        if (w != null && !w.filterName().isEmpty()) {
            // 如果@WebFilter注解不为空并且filterName属性不为空，则返回注解的filterName属性
            return w.filterName();
        }
        return defaultNameByClass(clazz);
    }

    /**
     * 获取Servlet的初始化参数
     * @param clazz Servlet字节码文件
     * @return 初始化参数
     */
    public static Map<String, String> getServletInitParams(Class<? extends Servlet> clazz) {
        WebServlet w = clazz.getAnnotation(WebServlet.class);
        if (w == null) {
            return Map.of();
        }
        return initParamsToMap(w.initParams());
    }

    /**
     * 获取Filter的初始化参数
     * @param clazz Filter字节码文件
     * @return 初始化参数
     */
    public static Map<String, String> getFilterInitParams(Class<? extends Filter> clazz) {
        WebFilter w = clazz.getAnnotation(WebFilter.class);
        if (w == null) {
            return Map.of();
        }
        return initParamsToMap(w.initParams());
    }

    /**
     * 获取Servlet的URL规则
     * @param clazz Servlet字节码文件
     * @return URL规则
     */
    public static String[] getServletUrlPatterns(Class<? extends Servlet> clazz) {
        WebServlet w = clazz.getAnnotation(WebServlet.class);
        if (w == null) {
            return new String[0];
        }
        return arraysToSet(w.value(), w.urlPatterns()).toArray(String[]::new);
    }

    /**
     * 获取Filter的URL规则
     * @param clazz Filter字节码文件
     * @return URL规则
     */
    public static String[] getFilterUrlPatterns(Class<? extends Filter> clazz) {
        WebFilter w = clazz.getAnnotation(WebFilter.class);
        if (w == null) {
            return new String[0];
        }
        return arraysToSet(w.value(), w.urlPatterns()).toArray(String[]::new);
    }

    public static EnumSet<DispatcherType> getFilterDispatcherTypes(Class<? extends Filter> clazz) {
        WebFilter w = clazz.getAnnotation(WebFilter.class);
        if (w == null) {
            return EnumSet.of(DispatcherType.REQUEST);
        }
        return EnumSet.copyOf(Arrays.asList(w.dispatcherTypes()));
    }

    /**
     * 通过字节码文件获取Servlet名称
     * @param clazz Servlet字节码文件
     * @return 默认名称
     */
    private static String defaultNameByClass(Class<?> clazz) {
        // 获取类名
        String name = clazz.getSimpleName();
        // 首字母小写
        name = Character.toLowerCase(name.charAt(0)) + name.substring(1);
        return name;
    }

    /**
     * 将WebInitParam数组转换为Map
     * @param params WebInitParam数组
     * @return Map集合
     */
    private static Map<String, String> initParamsToMap(WebInitParam[] params) {
        return Arrays.stream(params).collect(Collectors.toMap(p -> p.name(), p -> p.value()));
    }

    /**
     * 数组转成LinkedHashSet
     * @param arr1 String[]数组
     * @return Set
     */
    private static Set<String> arraysToSet(String[] arr1) {
        Set<String> set = new LinkedHashSet<>();
        for (String s : arr1) {
            set.add(s);
        }
        return set;
    }

    /**
     * 合并value和urlPatterns两个数组
     * @param arr1 value数组
     * @param arr2 urlPatterns数组
     * @return URL规则Set集合
     */
    private static Set<String> arraysToSet(String[] arr1, String[] arr2) {
        Set<String> set = arraysToSet(arr1);
        set.addAll(arraysToSet(arr2));
        return set;
    }
}
